using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using ZoneFiveSoftware.Common.Data.Fitness;
using ZoneFiveSoftware.Common.Data;
using ZoneFiveSoftware.Common.Visuals.Chart;
using FilteredStatistics.Common;

namespace FilteredStatistics.Common.Controller
{
    class ProxyDataTrackProvider : IActivityDataTrackProvider
    {
        public ProxyDataTrackProvider(object provider)
        {
            if (provider == null)
            {
                throw new Exception("Invalid provider pointer");
            }

            Type providerType = provider.GetType();

            m_ProviderObject = provider;

            m_GuidProperty = providerType.GetProperty("ReferenceId", typeof(Guid));
            m_IsPrimaryDataTrackProperty = providerType.GetProperty("IsPrimaryDataTrack", typeof(bool));
            m_ActivityProperty = providerType.GetProperty("Activity", typeof(IActivity));
            m_YAxisLabelProperty = providerType.GetProperty("YAxisLabel", typeof(String));
            m_YAxisUnitLabelProperty = providerType.GetProperty("YAxisUnitLabel", typeof(String));
            m_TrackColorProperty = providerType.GetProperty("TrackColor", typeof(Color));
            m_AxisFormatterProperty = providerType.GetProperty("AxisFormatter", typeof(IAxisFormatter));
            m_SmoothedDataTrackProperty = providerType.GetProperty("SmoothedDataTrack", typeof(INumericTimeDataSeries));
            m_DataTrackZoneGuidsProperty = providerType.GetProperty("DataTrackZoneGuids", typeof(IList<Guid>));
            m_DefaultZoneProperty = providerType.GetProperty("DefaultZone", typeof(Guid));
            m_GetDataTrackZoneNameMethod = providerType.GetMethod("GetDataTrackZoneName", new Type[] { typeof(Guid) });
            m_GetDataTrackZonesMethod = providerType.GetMethod("GetDataTrackZones", new Type[] { typeof(Guid) });
            m_DataTrackChangedEvent = providerType.GetEvent("DataTrackChanged");

            if (m_GuidProperty == null ||
                !m_GuidProperty.CanRead ||
                m_IsPrimaryDataTrackProperty == null ||
                !m_IsPrimaryDataTrackProperty.CanRead ||
                m_ActivityProperty == null ||
                !m_ActivityProperty.CanWrite ||
                m_YAxisLabelProperty == null ||
                !m_YAxisLabelProperty.CanRead ||
                m_YAxisUnitLabelProperty == null ||
                !m_YAxisUnitLabelProperty.CanRead ||
                m_TrackColorProperty == null ||
                !m_TrackColorProperty.CanRead ||
                m_AxisFormatterProperty == null ||
                !m_AxisFormatterProperty.CanRead ||
                m_SmoothedDataTrackProperty == null ||
                !m_SmoothedDataTrackProperty.CanRead ||
                m_DataTrackZoneGuidsProperty == null ||
                !m_DataTrackZoneGuidsProperty.CanRead ||
                m_DefaultZoneProperty == null ||
                !m_DefaultZoneProperty.CanRead ||
                m_GetDataTrackZoneNameMethod == null ||
                m_GetDataTrackZoneNameMethod.ReturnType != typeof(String) ||
                m_GetDataTrackZonesMethod == null ||
                m_GetDataTrackZonesMethod.ReturnType != typeof(IList<AxisStripe>) ||
                m_DataTrackChangedEvent == null)
            {
                throw new Exception("Provider doesn't implement DataTrackProvider interface");
            }

            m_DataTrackChangedEvent.AddEventHandler(m_ProviderObject, Delegate.CreateDelegate(typeof(PropertyChangedEventHandler), this, "DataTrackChangedEventHandler"));
        }

#region IActivityDataTrackProvider Members

        public Guid ReferenceId
        {
            get { return (Guid)m_GuidProperty.GetValue(m_ProviderObject, null); }
        }

        public bool IsPrimaryDataTrack
        {
            get
            {
                return (bool)m_IsPrimaryDataTrackProperty.GetValue(m_ProviderObject, null);
            }
        }

        public IActivity Activity
        {
            set
            {
                m_ActivityProperty.SetValue(m_ProviderObject, value, null);
            }
        }

        public string YAxisLabel
        {
            get
            {
                return m_YAxisLabelProperty.GetValue(m_ProviderObject, null) as string;
            }
        }

        public string YAxisUnitLabel
        {
            get
            {
                return m_YAxisUnitLabelProperty.GetValue(m_ProviderObject, null) as string;
            }
        }

        public Color TrackColor
        {
            get
            {
                return (Color)m_TrackColorProperty.GetValue(m_ProviderObject, null);
            }
        }

        public IAxisFormatter AxisFormatter
        {
            get
            {
                return m_AxisFormatterProperty.GetValue(m_ProviderObject, null) as IAxisFormatter;
            }
        }

        public INumericTimeDataSeries SmoothedDataTrack
        {
            get
            {
                return m_SmoothedDataTrackProperty.GetValue(m_ProviderObject, null) as INumericTimeDataSeries;
            }
        }

        public IList<Guid> DataTrackZoneGuids
        {
            get
            {
                return m_DataTrackZoneGuidsProperty.GetValue(m_ProviderObject, null) as IList<Guid>;
            }
        }

        public Guid DefaultZone
        {
            get
            {
                return (Guid)m_DefaultZoneProperty.GetValue(m_ProviderObject, null);
            }
        }

        public string GetDataTrackZoneName(Guid zoneId)
        {
            return m_GetDataTrackZoneNameMethod.Invoke(m_ProviderObject, new object[] { zoneId }) as string;
        }

        public IList<AxisStripe> GetDataTrackZones(Guid zoneId)
        {
            return m_GetDataTrackZonesMethod.Invoke(m_ProviderObject, new object[] { zoneId }) as IList<AxisStripe>;
        }

        public event PropertyChangedEventHandler DataTrackChanged;

#endregion

        private void DataTrackChangedEventHandler(object sender, PropertyChangedEventArgs e)
        {
            if (DataTrackChanged != null)
            {
                DataTrackChanged(this, e);
            }
        }

        private object m_ProviderObject = null;
        private PropertyInfo m_GuidProperty = null;
        private PropertyInfo m_IsPrimaryDataTrackProperty = null;
        private PropertyInfo m_ActivityProperty = null;
        private PropertyInfo m_YAxisLabelProperty = null;
        private PropertyInfo m_YAxisUnitLabelProperty = null;
        private PropertyInfo m_TrackColorProperty = null;
        private PropertyInfo m_AxisFormatterProperty = null;
        private PropertyInfo m_SmoothedDataTrackProperty = null;
        private PropertyInfo m_DataTrackZoneGuidsProperty = null;
        private PropertyInfo m_DefaultZoneProperty = null;
        private MethodInfo m_GetDataTrackZoneNameMethod = null;
        private MethodInfo m_GetDataTrackZonesMethod = null;
        private EventInfo m_DataTrackChangedEvent = null;
    }
}
